#include "Scenes.h"

#include <utility>
namespace Media{
    Scenes::Scenes(std::string  name):m_running(false), m_name(std::move(name)){
        m_videoMixer = std::make_shared<VideoMixer>();
        m_audioMixer = std::make_shared<AudioMixer>();

        //add default outSource

    }

    Scenes::~Scenes()= default;
    const std::string& Scenes::GetName(){
        return m_name;
    }
    // In Item Operate
    bool Scenes::AddVideoInItem(const ItemId& id,const VideoScenesInItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_videoMixer->AddItem(id, config);
    }
    bool Scenes::AddAudioInItem(const ItemId& id, const AudioScenesInItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_audioMixer->AddItem(id, config);
    }
    bool Scenes::SetVideoInItem(const ItemId& id, const VideoScenesInItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_videoMixer->SetItem(id, config);
    }
    bool Scenes::SetAudioInItem(const ItemId& id, const AudioScenesInItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_audioMixer->SetItem(id, config);
    }
    std::map<Scenes::ItemId, VideoScenesInItemConfig> Scenes::GetAllVideoInItem(){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        std::map<Scenes::ItemId, VideoScenesInItemConfig> items;
        m_videoMixer->GetItems(items);
        return items;
    }
    bool Scenes::GetVideoInItem(const Scenes::ItemId& id, VideoScenesInItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_videoMixer->GetOneInItem(id, config);
    }

    std::map<Scenes::ItemId, AudioScenesInItemConfig> Scenes::GetAllAudioInItem(){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        std::map<Scenes::ItemId, AudioScenesInItemConfig> items;
        m_audioMixer->GetItems(items);
        return items;
    }

    bool Scenes::GetAudioInItem(const Scenes::ItemId& id, AudioScenesInItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_audioMixer->GetOneInItem(id, config);
    }

    bool Scenes::DelVideoInItem(const ItemId& id){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_videoMixer->DelItem(id);
    }
    bool Scenes::DelAudioInItem(const ItemId& id){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_audioMixer->DelItem(id);
    }

     // Out Item Operate
    bool Scenes::SetVideoOutConfig(const VideoScenesOutItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        //must be set before running, to do check
        if(m_running) return false;

        if(m_videoMixer) return m_videoMixer->SetOutConfig(config);
        return false;
    }
    bool Scenes::SetAudioOutConfig(const AudioScenesOutItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        //must be set before running, to do check
        if(m_running) return false;

        if(m_audioMixer) m_audioMixer->SetOutConfig(config);
        return false;
    }
    bool Scenes::GetVideoOutConfig(VideoScenesOutItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_videoMixer) return m_videoMixer->GetOutConfig(config);
        return false;
    }
    bool Scenes::GetAudioOutConfig(AudioScenesOutItemConfig& config){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_audioMixer) return m_audioMixer->GetOutConfig(config);
        return false;
    }
    
    bool Scenes::AddVideoOutSource(OutputSource::OutputSourceId id,const std::string& name){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_videoMixer) return m_videoMixer->AddOutSource(id, name);
        return false;
    }
    bool Scenes::AddAudioOutSource(OutputSource::OutputSourceId id,const std::string& name){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_audioMixer) m_audioMixer->AddOutSource(id, name);
        return false;
    }
    bool Scenes::RemoveVideoOutSource(OutputSource::OutputSourceId id){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_videoMixer) return m_videoMixer->RemoveOutSource(id);
        return false;
    }
    bool Scenes::RemoveAudioOutSource(OutputSource::OutputSourceId id){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_audioMixer) return m_audioMixer->RemoveOutSource(id);
        return false;
    }

    bool Scenes::Start(){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_running) return false;

        if(!m_videoMixer && !m_audioMixer) return false;
        
        if(m_videoMixer) m_videoMixer->Start();
        if(m_audioMixer) m_audioMixer->Start();

        m_running = true;
        return true;
    }
    bool Scenes::IsRunning(){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        return m_running;
    }
    bool Scenes::Stop(){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        //1. stop videoMixer and audioMixer
        if(m_videoMixer) m_videoMixer->Stop();
        if(m_audioMixer) m_audioMixer->Stop();
        m_running = false;
        return true;
    }

    bool Scenes::SetFrameOutCb(const std::function<void (const FrameCommon::Frame::Ptr& frame)>& cb){
        std::lock_guard<std::recursive_mutex> guard(m_mux);
        if(m_videoMixer){
            m_videoMixer->SetDefaultOutCb(cb);
        }
        if(m_audioMixer){
            m_audioMixer->SetDefaultOutCb(cb);
        }
        return true;
    }
}